﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Text.RegularExpressions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace GS1.Utilitario
{
    /// <summary>
    /// <para>Clase       : Extensor</para>
    /// <para>Descripcion : Expone extension a objetos de .Net</para>
    /// <para>Autor       : Pedro Miguel Vera Rafael</para>
    /// <para>Fecha       : 17/05/2011</para>
    /// <para>Empresa     : GS1 Peru</para>
    /// </summary>
    public static class Extensor
    {
        #region --- Serializacion y Deserializacion XML ---

        /// <summary>
        /// Serializar a XML (UTF-16) un objeto cualquiera
        /// </summary>
        /// <param name="obj">objeto a serializar</param>
        /// <returns>Objeto serializado en formato XML</returns>
        public static string SerializarToXml(this object obj)
        {
            try
            {
                StringWriter strWriter = new StringWriter();
                XmlSerializer serializer = new XmlSerializer(obj.GetType());

                serializer.Serialize(strWriter, obj);
                string resultXml = strWriter.ToString();
                strWriter.Close();

                return resultXml;
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Deserializar un XML a un objeto T
        /// </summary>
        /// <typeparam name="T">Tipo del objeto a retornar</typeparam>
        /// <param name="xmlSerializado">Trama en formato XML</param>
        /// <returns>Objeto resultado</returns>
        public static T DeserializarTo<T>(this string xmlSerializado)
        {
            try
            {
                XmlSerializer xmlSerz = new XmlSerializer(typeof(T));

                using (StringReader strReader = new StringReader(xmlSerializado))
                {
                    object obj = xmlSerz.Deserialize(strReader);
                    return (T)obj;
                }
            }
            catch { return default(T); }
        }
        #endregion

        #region --- Serializacion y Deserializacion JSON ---

        /// <summary>
        /// Serializar a JSON cualquier objeto
        /// </summary>
        /// <param name="objeto">objeto a serializar</param>
        /// <returns>Objeto serializado en formato JSON</returns>
        public static string SerializaToJson(this object objeto)
        {
            string jsonResult = string.Empty;

            DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(objeto.GetType());
            MemoryStream ms = new MemoryStream();

            jsonSerializer.WriteObject(ms, objeto);
            jsonResult = Encoding.Default.GetString(ms.ToArray());
            ms.Dispose();

            return jsonResult;
        }

        /// <summary>
        /// Deserializar JSON a un objeto T
        /// </summary>
        /// <typeparam name="T">Tipo del objeto a retornar</typeparam>
        /// <param name="jsonSerializado">Trama en formato JSON</param>
        /// <returns>Objeto resultado</returns>
        public static T DeserializarJsonTo<T>(this string jsonSerializado)
        {
            T obj = Activator.CreateInstance<T>();
            MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonSerializado));
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());

            obj = (T)serializer.ReadObject(ms);
            ms.Close();
            ms.Dispose();

            return obj;
        }
        #endregion

        #region --- Formateo de cadenas ---
        /// <summary>
        /// Extensor: Que permite validar si la cadena enviada es del tipo Correo
        /// </summary>
        /// <param name="dataCorreo">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsFormatoCorreo(this string dataCorreo)
        {
            Regex regex = null;
            regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");

            //\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b
            return regex.IsMatch(dataCorreo);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Decimal
        /// </summary>
        /// <param name="dataDecimal">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsFormatoDecimal(this string dataDecimal)
        {
            Regex regex = null;
            regex = new Regex(@"[-+]?[0-9]*\.?[0-9]*");

            return regex.IsMatch(dataDecimal);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Entero con signo
        /// </summary>
        /// <param name="dataEntero">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsEnteroConSigno(this string dataEntero)
        {
            Regex regex = null;
            regex = new Regex(@"[-+]?[0-9]*");

            return regex.IsMatch(dataEntero);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Entero sin signo
        /// </summary>
        /// <param name="dataEntero">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsEnteroSinSigno(this string dataEntero)
        {
            Regex regex = null;
            regex = new Regex(@"[0-9]*");

            return regex.IsMatch(dataEntero);
        }
        #endregion

        #region --- Conversion Cadenas ---
        /// <summary>
        /// Extensor: Que permite convertir una cadena a Entero
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Entero</returns>
        public static int ToEntero(this string data)
        {
            int numero = 0;
            numero = Convert.ToInt32(data);
            return numero;
        }

        /// <summary>
        /// Extensor: Que permite convertir una cadena a Double
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Double</returns>
        public static double ToDouble(this string data)
        {
            double numero = 0;
            numero = Convert.ToDouble(data);
            return numero;
        }

        /// <summary>
        /// Extensor: Que permite convertir una cadena a Entero
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Decimal</returns>
        public static decimal ToDecimal(this string data)
        {
            decimal numero = 0;
            numero = Convert.ToDecimal(data);
            return numero;
        }
        #endregion

        #region --- Intervalo ---
        /// <summary>
        /// Extensor: Que permite comparar el minimo y maximo de un numero
        /// </summary>
        /// <typeparam name="T">Tipo de variable a compararse</typeparam>
        /// <param name="numero">Numero a compararse</param>
        /// <param name="minimo">Minimo valor</param>
        /// <param name="maximo">Maximo valor</param>
        /// <returns>True o False</returns>
        public static bool EstaEntre<T>(this T numero, T minimo, T maximo) where T : IComparable<T>
        {
            return numero.CompareTo(minimo) >= 0 && numero.CompareTo(maximo) <= 0;
        }
        #endregion

        #region --- Metodos de Encriptacion y Desencriptacion ---
        /// <summary>
        /// Funcion que permite de encriptar una cadena
        /// </summary>
        /// <param name="data">Cadena a ser desencriptada</param>
        /// <returns>Retorna Cadena desencriptada</returns>
        public static string Desencriptar(this string data)
        {
            byte[] bytes = Convert.FromBase64String(data);
            return Encoding.Default.GetString(bytes, 0, bytes.Length);
        }

        /// <summary>
        /// Funcion que permite encriptar una cadena
        /// </summary>
        /// <param name="data">Cadena a encriptar</param>
        /// <returns>Retorna Cadena encriptada</returns>
        public static string Encriptar(this string data)
        {
            byte[] bytes = Encoding.Default.GetBytes(data);
            return Convert.ToBase64String(bytes, 0, bytes.Length);
        }

        #endregion
    }
}
